/**
 * Created with  SublimeText
 * @Author:      Lyle
 * @DateTime:    2017-3-22 15:58:42
 * @Description: 局部注入插件，非全局插件
 */

//this.cacheFields  缓存对象
/*
  {
     username:{
        expression: "'required|email'" //rules
        el: el                         //元素   
        errorCode: 0, 1, 2 //0是初始化 1是通过， 2是错误
        errormsg: 'Required', //错误文本
        errorType: 'email' //错误类型
        need: true //是否需要验证该属性
        showError : true //是否显示错误提示
     }
   
     password: {
        ....
     }
  }
*/

import Vue from 'vue'

//创建自定义指令
Vue.directive('validate', {
    bind(el, binding, vnode, oldVnode) {
        //console.log('bind', el, binding, vnode.context, oldVnode);
        let vm = vnode.context;
        //name = vm.$route.name;
        vm.addValidationField(el, binding);
        el.oninput = () => {
            let elName = el.getAttribute('name');
            vm.validateOne(elName);
        };
    }
})

//验证插件依赖状态属性及相关方法，注入到组件，解耦。
var validationMixin = {

    beforeCreate: function() {
        this.cacheFields = {};
        this.errorText = {
            'required': 'Required!',
            'email': 'email error!',
            'min': 'min error!',
            'max': 'max error!',
            'password': 'password error!',
            'username': 'username error!'
        };
    },

    methods: {

        changeField: function(elName, key, value) {
            this.cacheFields[elName][key] = value;
        },

        changeCacheFields: function(elName, obj) {
            //console.log('changeCacheFields', elName, obj, this.cacheFields);
            this.cacheFields[elName].errormsg = obj.errormsg;
            this.cacheFields[elName].errorCode = obj.errorCode;
        },

        clearElNameValue: function(elName) {
            this.cacheFields[elName].errorCode = 0;
            this.cacheFields[elName].errormsg = '';
        },

        addValidationField: function(el, binding) {
            var elName = el.getAttribute('name'),
                expression = binding.expression,
                arg = binding.arg;
            this.cacheFields[elName] = {
                expression: expression,
                el: el,
                errorCode: 0,
                errormsg: '',
                errorType: '',
                need: (arg == 'lazy') ? false : true,
                showError: true,
            }
        },

        validateOne: function(elName) {
            if (this.cacheFields[elName]) {
                this.validationItem(this.cacheFields[elName].el, this.cacheFields[elName].expression);
            }
        },

        pipelineValidation: function(value, str) {

            var type, errorBool = false,
                arr = str.replace(/\'/g, "").split('|');

            for (let i in arr) {
                type = arr[i];
                errorBool = this.checkValue(value, arr[i]);
                //console.log(46, errorBool, type);
                if (!errorBool) {
                    break;
                }
            }
            return { bool: errorBool, type: type };
        },

        checkValue: function(value, type) {
            var bool = true,
                emailReg = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
                userName = /^[a-zA-Z0-9_]{1}[a-zA-Z0-9_]{5,17}$/; //兼容老注册首字符使用数字的用户
            switch (type) {
                case 'required':
                    if (!value) {
                        bool = false;
                    }
                    break;

                case 'min':
                    if (value.length < 6) {
                        bool = false;
                    }
                    break;

                case 'max':
                    if (value.length > 18) {
                        bool = false;

                    }
                    break;

                case 'email':
                    if (!emailReg.test(value)) {
                        bool = false;
                    }
                    break;

                case 'username':
                    if (!userName.test(value)) {
                        bool = false;
                    }
                    break;
                case 'usernameORemail':
                    if (value.indexOf('@') > -1) {
                        if (!emailReg.test(value)) {
                            bool = false;
                        }
                    } else {
                        if (!userName.test(value)) {
                            bool = false;
                        }
                    }
                    break;
                default:
                    console.log('the rule is not found!');
            }
            return bool;
        },

        getValidationErrorText: function(errorType, value) {
            var errorText;
            if (errorType == 'usernameORemail') {
                if (value.indexOf('@') > -1) {
                    errorText = this.errorText['email'];
                } else {
                    errorText = this.errorText['username'];
                }
            } else {
                errorText = this.errorText[errorType];
            }
            return errorText;
        },

        validateEach: function() {
            for (let i in this.cacheFields) {
                if (this.cacheFields[i].need) {
                    this.validationItem(this.cacheFields[i].el, this.cacheFields[i].expression);
                }
            }
        },

        validationValue: function(el, errorType, errorCode) {
            var elName = el.getAttribute('name');
            this.cacheFields[elName].errormsg = (errorCode == 2) ? this.getValidationErrorText(errorType, el.value) : '';
            this.cacheFields[elName].errorType = errorType;
            this.cacheFields[elName].errorCode = errorCode;
        },

        validationItem: function(el, expression) {
            var obj = this.pipelineValidation(el.value, expression),
                errorCode = (obj.bool) ? 1 : 2;
            this.validationValue(el, obj.type, errorCode);
        },


        checkOne: function(elName) {
            var bool = true;
            if (this.cacheFields[elName].errorCode == 2 && this.cacheFields[elName].need) {
                bool = false;
            }
            return bool;
        },

        checkAll: function() {
            //console.log('checkAll', this.cacheFields);
            this.validateEach();
            return this.checkCacheAll();
        },

        checkCacheAll: function() {
            //console.log('checkAll', this.cacheFields);
            var bool = true;
            for (var i in this.cacheFields) {
                if ((this.cacheFields[i].errorCode == 2 || this.cacheFields[i].errorCode == 0) && this.cacheFields[i].need) {
                    bool = false;
                }
            }
            return bool;
        },

        checkOneAll: function(name) {
            var bool = true;
            this.validateOne(name);
            for (var i in this.cacheFields) {
                if ((this.cacheFields[i].errorCode == 2 || this.cacheFields[i].errorCode == 0) && this.cacheFields[i].need) {
                    bool = false;
                }
            }
            return bool;
        },

        hasValidateError: function(elName) {
            //console.log('hasValidateError', elName, this.cacheFields[elName], this.cacheFields);
            let bool = false;
            if (this.cacheFields[elName] && this.cacheFields[elName].errorCode == 2 && this.cacheFields[elName].need) {
                bool = true;
            }
            if (this.cacheFields[elName] && !this.cacheFields[elName].showError) {
                bool = false;
            }
            return bool;
        },

        getValidateError: function(elName) {
            let msg = this.cacheFields[elName] && this.cacheFields[elName].errormsg ? this.cacheFields[elName].errormsg : '';
            if (this.cacheFields[elName] && !this.cacheFields[elName].showError) {
                return '';
            } else {
                return msg;
            }

        },

        getOneValidateError() {
            return this.cacheFields[0].errormsg;
        },

        getCacheFields() {
            return this.cacheFields;
        }

    }
}

export default validationMixin;
